import math
import xml.etree.cElementTree as et
import os

# 字典类型的数据，三分类
class_num={
    'person':0,
    'horse':1,
    'bicycle':2
}
# os.listdir 函数用于获取指定目录下的所有文件和文件夹的名称，并以列表的形式返回
xml_dir='data/image_voc'
xml_filenames=os.listdir(xml_dir)
# 使用了 open 函数来打开名为 data.txt 的文件，并将 f作为文件对象进行操作。文件被以附加模式 'a' 打开
# 通过 with 语句，文件将在代码块结束后自动关闭，这是推荐的文件操作方式，可以避免资源泄露。
with open('data.txt','a') as f:
    for xml_filename in xml_filenames:
        xml_filename_path=os.path.join(xml_dir,xml_filename)
        tree=et.parse(xml_filename_path)
        root=tree.getroot()
        filename=root.find('filename')     # 该图片对应的名称
        names=root.findall('object/name')     # 一张图片中，对应所有标签的类别名称
        boxes=root.findall('object/bndbox')   # 一张图片中，对应所有标签的ground truth <xmin,ymin,xmax,ymax> 左上角坐标和右下角坐标

        data=[]  # 定义一个空列表
        data.append(filename.text)
        # zip 函数将两个或多个可迭代对象对应位置上的元素打包成一个元组，然后返回一个由这些元组组成的迭代器。在每次循环迭代中，name 和 box 分别表示当前迭代位置上的元素。
        for name,box in zip(names,boxes):
            cls=class_num[name.text] # 标签类别名称对应的编号cls
            # math.floor() 函数，该函数返回小于或等于传入参数的最大整数。这里通过计算得出了{cx,cy,w,h}中心点坐标和宽高
            cx=math.floor((int(box[2].text)+int(box[0].text))/2)
            cy=math.floor((int(box[3].text)+int(box[1].text))/2)
            w=int(box[2].text)-int(box[0].text)
            h=int(box[3].text)-int(box[1].text)
            data.append(cls)
            data.append(cx)
            data.append(cy)
            data.append(w)
            data.append(h)
        # 将data列表，转换为字符串，并写入文件
        _str=''
        for i in data:
            _str=_str+' '+str(i)
        f.write(_str+'\n')
# f.close() 记得在使用完文件后，不要忘记关闭文件，但是在使用 with 语句中，不用手动关闭文件，因为它会自动关闭。